package js.android.nateroidbeta;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Vector;

import rath.nateon.ChatChannel;
import rath.nateon.Debug;
import rath.nateon.NateOnMessenger;
import rath.nateon.NateUser;
import rath.nateon.NotificationChannel;
import rath.nateon.event.NateOnAdapter;
import rath.nateon.event.NateOnListener;
import android.os.Handler;

import js.android.nateroidbeta.ChatScreen.ChatRecord;
import js.android.nateroidbeta.FriendList.BuddyListEntity;
import js.android.nateroidbeta.event.OnGoingChatListener;


public final class NateOnSingleton {
	private static NateOnSingleton m_instance = null;
	private static NateOnMessenger m_nateon = null;
	private static String m_strUserID;
	private static String m_strPassword;
	private static UIStatus m_Status = UIStatus.OnLogin;
	private static ChatChannel m_chatChannel = null;
	private static NotificationChannel m_notification = null;
	private static Vector m_l = new Vector();
	private static NateUser m_CurrChatPartner = null;
	private static HashMap m_OnGoingChatMap = new HashMap();
	private static OnGoingChatListener m_onGoingChatListner = null;
	private static ChatScreen m_chatScreen = null;
	private static Handler m_onGoingChatHandler = null;
	private static boolean m_IsLogInSuccess = false;

	
	protected NateOnSingleton(){

    	Debug.printInput = true;
		Debug.printOutput = true;
				
	}
	
	public static final void SetStatus(UIStatus curStatus)
	{
		m_Status = curStatus;
	}
	
	public static boolean Login()
	{
		try{
		if(m_strUserID == null || m_strPassword == null)
			return false;
		
		Debug.printOutput = true;
		Debug.printInput = true;
		final Object lock = new Object();
		
		m_nateon = new NateOnMessenger(m_strUserID, m_strPassword);
		m_nateon.setAutoAccept(true);
		m_nateon.setAuthInfo(m_strUserID, m_strPassword);
		NateOnAdapter listner = new NateOnAdapter(){
			public void loginComplete(NateUser me)
			{
				System.out.println("* Login complete:" + me);
				m_IsLogInSuccess = true;

				synchronized(lock)
				{
					lock.notify();
				}
			}
			
			public void smsReceived( String from, String to, String msg)
				throws IOException
			{
				System.out.println("* SMS from: " + from );
				System.out.println( msg );
			}
			
			public void channelMessage(ChatChannel channel, String from, String font, String msg )
			{
				System.out.println( from + "says: " + msg);

				String email = m_CurrChatPartner.getEmail();
//				if(from == m_CurrChatPartner.getEmail() )
				{
					if(m_chatScreen != null)
					{
						m_chatScreen.Add(from,msg);
						m_chatScreen.MsgFromPeer();
					}
				}

//				}
//				catch( IOException e)
//				{
//					e.printStackTrace();
//				}
			}
			
			public void loginFailed()
			{
				//TODO: show message
				m_IsLogInSuccess = false;
				synchronized(lock)
				{
					lock.notify();
				}
			}
		};
		
		m_nateon.addNateOnListener(listner);
		m_nateon.loginWait();
		synchronized(lock)
		{
			lock.wait(20000);
		}
//		m_nateon.removeNateOnListener(listner );
		return m_IsLogInSuccess;
		}catch(Exception e)
		{
			e.printStackTrace();
			return false;
		}
	}
			
	public static final  ArrayList getFriendsList()
	{
		if(m_notification == null)
			m_notification = m_nateon.getNotificationChannel();
	
		return m_notification.getFriendsList();
	}
	
	public static final void SetUserID(String strUserID, String strPassword)
	{
		m_strUserID = strUserID;
		m_strPassword = strPassword;
	}
	
	public static final boolean IsLoggedIn()
	{
		if(m_nateon == null)
			return false;
		return m_nateon.isLoggedIn();	
	}
	
	public static final void setOnGoingChatListener(OnGoingChatListener l)
	{
		m_onGoingChatListner = l;
	}
	
	public static final void setChatScreenHandler(Handler handler)
	{
		m_onGoingChatHandler = handler;
	}
	
	public static final void setChatScreen(ChatScreen chatScreen)
	{
		m_chatScreen = chatScreen;
	}
	
	public static final void delOnGoingChatListener()
	{
//		if(m_onGoingChatListner != null)
//			delete m_onGoingChatListner;	// it's java.. don't worry about leak;
	}
	
	public static final void AddOnGoingChat(String strEmail)
	{
		if(!m_OnGoingChatMap.containsKey(strEmail))
			m_OnGoingChatMap.put(strEmail, new ArrayList<ChatRecord>());
	}
	
	public static final void DelOnGoingChat(String strEmail)
	{
		if(m_OnGoingChatMap.containsKey(strEmail))
			m_OnGoingChatMap.remove(strEmail);
	}
	/*
	public static final ArrayList<ChatRecord> getOnGoingChat(String strEmail)
	{
		if(!m_OnGoingChatMap.containsKey(strEmail))
			return (ArrayList<ChatRecord>)m_OnGoingChatMap.get(strEmail);
		
		else
			return null; 	//or throws exception
	}
	*/
	public static final ArrayList<ChatRecord> getCurChatLog()
	{
		if(m_OnGoingChatMap.containsKey(m_CurrChatPartner.getEmail() ))
			return (ArrayList<ChatRecord>)m_OnGoingChatMap.get(m_CurrChatPartner.getEmail());
		else
			return null;		// or throws exception
	}
	
	public static class WrappedChatChannel
	{
		ChatChannel channel;
	}
	
	public static final boolean CallAndInvite(final String email)
	throws IOException, InterruptedException
	{
		final WrappedChatChannel channel = new WrappedChatChannel();
		final Object lock = new Object();
		
		NateOnListener temp = new NateOnAdapter() {
			String sessionId = null;
			public void channelOpened( ChatChannel chan ) throws IOException
			{
				sessionId = chan.getSessionId();
				invite( chan, email );
			}
			public void channelJoined( ChatChannel chan, NateUser user ) throws IOException
			{
				if( sessionId!=null && chan.getSessionId().equals(sessionId) &&
					user.getEmail().equals(email) )
				{
					channel.channel = chan;
					synchronized(lock)
					{
						lock.notify();
					}
				}
			}
			public void channelCancel( ChatChannel chan ) throws IOException
			{
				if( sessionId!=null && chan.getSessionId().equals(sessionId) )
				{
					synchronized(lock)
					{
						lock.notify();
					}					
				}
			}
		};
		
		addNateOnListener( temp );
		createChannel();
		
		synchronized(lock)
		{
			lock.wait(70000);
		}
		removeNateOnListener( temp );
		
		if(channel.channel != null )
		{
			m_chatChannel = channel.channel;
			m_CurrChatPartner = getNateUser(email);
			AddOnGoingChat(email);
			return true;
		}
		else
		{
			m_chatChannel = null; 
			return false;
		}
			
//		return channel.channel;
	}
	
	public static NateUser getNateUser(String strEmail)
	{
		ArrayList<NateUser> friendsList = getNotificationChannel().getFriendsList();
		
		for(int i = 0; i < friendsList.size(); i++)
		{
			NateUser Friend = friendsList.get(i); 
			
			if(strEmail == Friend.getEmail())
			{
				return Friend;
			}
		}		
		return null;
	}
	
	public static NotificationChannel getNotificationChannel()
	{
		if(m_notification == null)
			m_notification = m_nateon.getNotificationChannel();
		
		return m_notification;
	}
	
	public static void invite( ChatChannel chat, String email ) throws IOException
	{
	
		getNotificationChannel().invite( chat, email );
	}

	public static void addNateOnListener( NateOnListener l )
	{
		m_nateon.addNateOnListener(l);
		/*
		if( !m_l.contains(l) )
			m_l.add( l );
			*/
	}

	public static void removeNateOnListener( NateOnListener l )
	{
		m_nateon.removeNateOnListener(l);	
//		m_l.removeElement(l);
	}
	
	public static void createChannel() throws IOException
	{
		m_notification.createChannel();
	}
	
	public static void SendMessage(String strMsg)
	{
		try{
			m_chatChannel.sendMessage( strMsg );
		}catch(Exception e)
		{
			e.printStackTrace();			
		}
	}
	
	public static void setPartner(String email )
	{
		m_CurrChatPartner = getNateUser(email);
	}
		
	public static NateUser getPartner()
	{
		return m_CurrChatPartner;
	}
	
	public static String getEmail()
	{
		return m_strUserID; 
	}
	
	public static String getName()
	{
		return m_nateon.getOwner().getName(); 
	}
	
	public static String getNickname()
	{
		return m_nateon.getOwner().getNickname();
	}
	
	public static NateUser getOwner()
	{
		return m_nateon.getOwner();
	}
}



